package com.chapter7.neibulei.demo6;


/**
 * 匿名内部类：在方法中定义内部类，甚至在语句块中定义内部类；
 *
 * 这种情况通常是某个方法需要创建一个类来辅助完成该方法的功能，而这个类只用在该方法中。
 *
 * 局部内部类需要配合接口来一起使用。
 */
public class LocalInnerClass {

    Speaker getSpeaker(String str) {

        /**
         * 我们定义了一个局部内部类MySpeaker，该类只能在getSpeaker方法内部访问，
         * 外部访问该类的对象是通过其实现的接口Speaker来访问的。
         * 既然如此，这个类有没有名字就不重要了，那么可以将其改造成匿名的内部类
         */
//        class Myspeaker implements Speaker {
//            @Override
//            public void speak() {
//                //在局部内部类中可以直接访问方法的参数str，这样就可以减少内部类的实例变量数。
//                System.out.println(str);
//            }
//        }
//
//        //返回Speaker接口类型的对象
//        return new Myspeaker();


        /**
         * “new Speaker（）{…}；”去掉一对花括号及其中的内容，变成“new Speaker（）；”，就是创建对象的语法
         * 然而Speaker是接口，是无法实例化的，需要有接口的实现，
         * 于是在“Speaker（）”和“；”之间，以一对花括号给出接口的实现，该实现没有类名，其实就是匿名的内部类。
         */
        return new Speaker(){
            @Override
            public void speak() {
                //在局部内部类中可以直接访问方法的参数str，这样就可以减少内部类的实例变量数。
                System.out.println(str);
            }
        };

    }


    /**
     * （1）创建LocalInnerClass类的对象lic。
     * （2）调用lic的getSpeaker方法，传入实参“Local inner class”，方法形参str有值了。
     * （3）getSpeaker方法返回Speaker接口类型的对象，该方法结束，清理方法所在的栈空间，形参str被清理。
     * （4）调用Speaker对象的speak方法，输出getSpeaker方法的形参str的值。
     */
    public static void main(String[] args) {
        LocalInnerClass lic = new LocalInnerClass();
        lic.getSpeaker("Local inner class").speak();
    }

}
